package com.chj.chuji.tijie07;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;

//#include <bits/stdc++.h>
//using namespace std;
//const double inf = 1e9;
//const double eps = 1e-9;
//const int maxn = 1010;
//int N, n;
//double A, B, C1, C2;
//double dist[maxn];
//bool vis[maxn];
//
//struct Node
//{
//    int v;
//    double c;
//    Node (int _v, double _c): v(_v), c(_c) {}
//    bool operator < (const Node & r) const
//    {
//        return c > r.c;
//    }
//};
//
//struct Edge
//{
//    int to;
//    double cost;
//    Edge(int _to, double _cost): to(_to), cost(_cost) {}
//};
//
//vector <Edge> edge[maxn];
//
//void addedge(int u, int v, double w)
//{
//    edge[u].push_back(Edge(v, w));
//}
//
//struct Circle
//{
//    double x, y, r;
//}circle[maxn];
//
//double dist1(Circle a, Circle b) // 两个“圆”的距离
//{
//    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) - a.r - b.r;
//}
//
//double dist2(double C, Circle d) // “圆”到直线的距离
//{
//    return (fabs(A * d.x + B * d.y  + C) / sqrt(A * A + B * B) - d.r);
//}
//
//double dijkstra(int s, int t) // 最短路
//{
//    for (int i = 0; i <= N; ++i)
//    {
//        dist[i] = inf;
//        vis[i] = false;
//    }
//    dist[s] = 0;
//    priority_queue <Node> Q;
//    Q.push(Node(s, dist[s]));
//    while (!Q.empty())
//    {
//        Node tmp = Q.top();
//        Q.pop();
//        int u = tmp.v;
//        if (u == t) //  到达t即返回
//            return tmp.c;
//        if (vis[u])
//            continue;
//        vis[u] = true;
//        for (int i = 0; i < edge[u].size(); ++i)
//        {
//            int v = edge[u][i].to;
//            double cost = edge[u][i].cost;
//            if (!vis[v] && dist[v] > dist[u] + cost)
//            {
//                dist[v] = dist[u] + cost;
//                Q.push(Node(v, dist[v]));
//            }
//        }
//    }
//    return 0;
//}
//
//int main()
//{
//    scanf("%d%lf%lf%lf%lf", &n, &A, &B, &C1, &C2);
//    for (int i = 1; i <= n; ++i)
//        scanf("%lf%lf%lf", &circle[i].x, &circle[i].y, &circle[i].r);
//    N = n + 1; // 总点数
//    for (int i = 1; i <= n; ++i) // 起点与圆
//    {
//        double w = dist2(C1, circle[i]);
//        if (w > eps)
//            addedge(0, i, w);
//        else
//            addedge(0, i, 0);
//    }
//    for (int i = 1; i <= n; ++i) // 圆与终点
//    {
//        double w = dist2(C2, circle[i]);
//        if (w > eps)
//            addedge(i, N, w);
//        else
//            addedge(i, N, 0);
//    }
//    for (int i = 1; i <= n; ++i) // 圆间
//    {
//        for (int j = 1; j <= n; ++j)
//        {
//            double w = dist1(circle[i], circle[j]);
//            if (w > eps)
//            {
//                addedge(i, j, w);
//                addedge(j, i, w);
//            }
//            else
//            {
//                addedge(i, j, 0);
//                addedge(j, i, 0);
//            }
//        }
//    }
//    double ans = dijkstra(0, N);
//    printf("%.7f\n", ans);
//    return 0;
//}

public class NewGame02 {

	public static class Circle {
		public int x, y, r;

		public Circle(int x, int y, int r) {
			this.x = x;
			this.y = y;
			this.r = r;
		}
	}

	public static class Edge {
		public int to;
		public double cost;

		public Edge(int to, double cost) {
			this.to = to;
			this.cost = cost;
		}
	}

	public static class EdgeList {
		public ArrayList<Edge> le;

		public EdgeList() {
			this.le = new ArrayList<Edge>();
		}
	}

	public static int n = 2;
	public static int A = 0;
	public static int B = 1;
	public static int N = n + 1;
	public static final int maxn = 10;
	public static final double inf = 1e9;
	public static final double eps = 1e-9;

	public static void main(String[] args) {
		for (int i = 0; i < 10; i++) {
			EdgeList edgeList = new EdgeList();
			edge[i] = edgeList;
		}

//		int n = 2;
//		int A = 0;
//		int B = 1;
		int C1 = 0;
		int C2 = -4;
//		int maxn = 1010;
//		int N = 0;

		Circle[] circle = new Circle[maxn];
		Circle cir01 = new Circle(0, 1, 1);
		Circle cir02 = new Circle(1, 3, 1);
		circle[1] = cir01;
		circle[2] = cir02;
		N = n + 1; // 总点数

		for (int i = 1; i <= n; ++i) // 起点与圆
		{
			double w = dist2(C1, circle[i]);
			if (w > eps)
				addedge(0, i, w);
			else
				addedge(0, i, 0);
		}

		for (int i = 1; i <= n; ++i) // 圆与终点
		{
			double w = dist2(C2, circle[i]);
			if (w > eps)
				addedge(i, N, w);
			else
				addedge(i, N, 0);
		}

		for (int i = 1; i <= n; ++i) // 圆间
		{
			for (int j = 1; j <= n; ++j) {
				double w = dist1(circle[i], circle[j]);
				if (w > eps) {
					addedge(i, j, w);
					addedge(j, i, w);
				} else {
					addedge(i, j, 0);
					addedge(j, i, 0);
				}
			}
		}

		double ans = dijkstra(0, N);
//	    printf("%.7f\n", ans);
		System.out.println(String.format("%.6f", ans));
	}

	public static EdgeList[] edge = new EdgeList[maxn];

//	public static (ArrayList<Edge>)[] edge222 = new (ArrayList<Edge>)[maxn];
	public static double[] dist = new double[maxn];
	public static boolean[] vis = new boolean[maxn];
	public static PriorityQueue<Node> heap = new PriorityQueue<>(new NodeComparator());

	public static class Node {
		public int v;
		public double c;

		public Node(int v, double c) {
			this.v = v;
			this.c = c;
		}
	}

	public static class NodeComparator implements Comparator<Node> {

		@Override
		public int compare(Node o1, Node o2) {
			if (o1.c > o2.c) {
				return 1;
			} else if (o1.c < o2.c) {
				return -1;
			}
			return 0;
		}

	}

	public static void addedge(int u, int v, double w) {
		edge[u].le.add(new Edge(v, w));
	}

	public static double dist1(Circle a, Circle b) // 两个“圆”的距离
	{
		return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) - a.r - b.r;
	}

	public static double dist2(double C, Circle d) // “圆”到直线的距离
	{
		return (Math.abs(A * d.x + B * d.y + C) / Math.sqrt(A * A + B * B) - d.r);
	}

	public static double dijkstra(int s, int t) // 最短路
	{
		for (int i = 0; i <= N; ++i) {
			dist[i] = inf;
			vis[i] = false;
		}
		dist[s] = 0;
//		priority_queue<Node> Q;
		Node node01 = new Node(s, dist[s]);
		heap.add(node01);
		while (!heap.isEmpty()) {
			Node tmp = heap.peek();
			heap.poll();
			int u = tmp.v;
			if (u == t) // 到达t即返回
				return tmp.c;
			if (vis[u])
				continue;
			vis[u] = true;
			for (int i = 0; i < edge[u].le.size(); ++i) {
				int v = edge[u].le.get(i).to;
				double cost = edge[u].le.get(i).cost;
				if (!vis[v] && dist[v] > dist[u] + cost) {
					dist[v] = dist[u] + cost;
					Node node02 = new Node(v, dist[v]);
					heap.add(node02);
				}
			}
		}
		return 0;
	}

}
